﻿using Clueless;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace Clueless
{
    public class Network
    {
        public event EventHandler<DebugMessageEventArgs> DebugMessage;
        public event EventHandler<AddCardEventArgs> AddCardMessage;
        public event EventHandler<CharacterSelectEventArgs> CharacterSelectMessage;
        public event EventHandler<SyncCharacterArgs> SyncCharacterMessage;
        public event EventHandler<StartTurnEventArgs> StartTurn;
        public event EventHandler<SuggestionMadeEventArgs> SuggestionMade;
        public event EventHandler<SuggestionMadeEventArgs> DisproveMade;
        public event EventHandler<SuggestionMadeEventArgs> AccusationResponse;
        public event EventHandler<SuggestionMadeEventArgs> PlayerLost;


        public Socket clientSocket; //The main client socket
        public string strName;      //Name by which the user logs into the room

        private byte[] byteData = new byte[1024];

        public Network()
        {
            //this.Text = "SGSclientTCP: " + strName;
            Random rnd = new Random();
            strName = "Test " + rnd.Next(1, 9999).ToString();
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPAddress ipAddress = IPAddress.Parse("10.0.0.12");
                //Server is listening on port 1000
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 1000);

                //Connect to the server
                clientSocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);

                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
        }

        public Network(String ip, String port)
        {
            //this.Text = "SGSclientTCP: " + strName;
            Random rnd = new Random();
            strName = "Test " + rnd.Next(1, 9999).ToString();
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPAddress ipAddress = IPAddress.Parse(ip);
                //Server is listening on port 1000
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Convert.ToInt32(port));

                //Connect to the server
                clientSocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CompleteConnection()
        {

            //The user has logged into the system so we now request the server to send
            //the names of all users who are in the chat room
            Data msgToSend = new Data();
            msgToSend.cmdCommand = MessageType.List;
            msgToSend.strName = strName;
            msgToSend.strMessage = null;

            byteData = msgToSend.ToByte();

            clientSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnSend), null);

            byteData = new byte[1024];
            //Start listening to the data asynchronously
            clientSocket.BeginReceive(byteData,
                                       0,
                                       byteData.Length,
                                       SocketFlags.None,
                                       new AsyncCallback(OnReceive),
                                       null);
        }

        public void KillConnection()
        {
            /*if (MessageBox.Show("Are you sure you want to leave the chat room?", "SGSclient: " + strName,
                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
            {
                //e.Cancel = true;
                return;
            }
            
            try
            {
                //Send a message to logout of the server
                Data msgToSend = new Data();
                msgToSend.cmdCommand = MessageType.Logout;
                msgToSend.strName = strName;
                msgToSend.strMessage = null;

                byte[] b = msgToSend.ToByte();
                clientSocket.Send(b, 0, b.Length, SocketFlags.None);
                clientSocket.Close();
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
             * */
        }

        

        private void OnSend(IAsyncResult ar)
        {
            try
            {
                clientSocket.EndSend(ar);
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnSendConnection(IAsyncResult ar)
        {
            try
            {
                clientSocket.EndSend(ar);
                CompleteConnection();
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private void OnConnect(IAsyncResult ar)
        {
            try
            {

                Console.WriteLine("OnConnect");

                clientSocket.EndConnect(ar);

                //We are connected so we login into the server
                Data msgToSend = new Data();
                msgToSend.cmdCommand = MessageType.Login;
                msgToSend.strName = strName;
                msgToSend.strMessage = null;

                byte[] b = msgToSend.ToByte();

                //Send the message to the server
                Console.WriteLine("Send Socket");

                clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSendConnection), null);
                Console.WriteLine("After Send Socket");

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private void OnReceive(IAsyncResult ar)
        {
            try
            {
                
                clientSocket.EndReceive(ar);

                Data msgReceived = new Data(byteData);
                Console.WriteLine("OnReceive " + msgReceived.cmdCommand);
                //Accordingly process the message received
                switch (msgReceived.cmdCommand)
                {
                    case MessageType.Login:
                        //SendAddCharacterMessage(msgReceived.me);
                        break;

                    case MessageType.Logout:
                        //RemoveFromChatters(msgReceived.strName);
                        break;

                    case MessageType.Message:
                        break;

                    case MessageType.List:
                        //AddChattersList(msgReceived.strMessage);
                        SendDebugMessage("<<<" + strName + " has joined the room>>>\r\n");
                        break;
                    case MessageType.AddCard:
                        SendAddCardMessage(msgReceived.strMessage);
                        break;
                    case MessageType.ChooseCharacter:
                        Console.WriteLine("ChooseCharacter!!");
                        SendCharacterSelectMessage(msgReceived.strMessage);
                        break;
                    case MessageType.SyncChar:
                        SendSyncCharacterMessage(msgReceived.strMessage);
                        break;
                    case MessageType.Turn:
                        SendStartTurnMessage(msgReceived.strMessage);
                        break;
                    case MessageType.Suggest:
                        Console.WriteLine("Suggest - NETWORK");
                        SendSuggestionMadeMessage(msgReceived.strMessage, msgReceived.strName);
                        break;
                    case MessageType.SuggestResponse:
                        Console.WriteLine("Suggestion response: " + msgReceived.strMessage);
                        SendDisproveMadeMessage(msgReceived.strMessage, msgReceived.strName);
                        break;
                    case MessageType.AccuseResponse:
                        Console.WriteLine("Accusation response: " + msgReceived.strMessage + " by " + msgReceived.strName);
                        //////////////////////
                        SendAccusationResponseMadeMessage(msgReceived.strMessage, msgReceived.strName);
                        break;
                    case MessageType.PlayerLost:
                        SendPlayerLostMessage(msgReceived.strName);
                        break;
                }

                if (msgReceived.strMessage != null && msgReceived.cmdCommand != MessageType.List)
                    SendDebugMessage(msgReceived.strMessage + "\r\n");

                byteData = new byte[1024];

                clientSocket.BeginReceive(byteData,
                                          0,
                                          byteData.Length,
                                          SocketFlags.None,
                                          new AsyncCallback(OnReceive),
                                          null);

            }
            catch (ObjectDisposedException)
            { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void Connect()
        {
            throw new System.NotImplementedException();
        }

        public void SendHearbeat()
        {
            throw new System.NotImplementedException();
        }

        public void SendMessage(String text, String name, MessageType type)
        {
            Data data = new Data();
            data.cmdCommand = type;
            data.strName = name;
            data.strMessage = text;

            byte[] message = data.ToByte();

            clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None,
                                new AsyncCallback(OnSend), clientSocket);

        }


        private void SendAddCardMessage(String cardName)
        {
            AddCardEventArgs args = new AddCardEventArgs();
            args.messageType = MessageType.AddCard;
            args.cardName = cardName;
            OnAddCardMessage(args);
        }
        protected virtual void OnAddCardMessage(AddCardEventArgs e)
        {
            EventHandler<AddCardEventArgs> handler = AddCardMessage;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        private void SendDebugMessage(String s)
        {
            DebugMessageEventArgs args = new DebugMessageEventArgs();
            args.message = s;
            args.messageType = MessageType.Null;
            OnDebugMessage(args);
        }
        protected virtual void OnDebugMessage(DebugMessageEventArgs e)
        {
            EventHandler<DebugMessageEventArgs> handler = DebugMessage;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        private void SendCharacterSelectMessage(String s)
        {
            Console.WriteLine("SendChooseCharacter!!");
            CharacterSelectEventArgs args = new CharacterSelectEventArgs();
            args.names = s;
            OnCharacterSelectMessage(args);
        }
        protected virtual void OnCharacterSelectMessage(CharacterSelectEventArgs e)
        {
            Console.WriteLine("OnChooseCharacter!!");
            EventHandler<CharacterSelectEventArgs> handler = CharacterSelectMessage;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        private void SendSyncCharacterMessage(String s)
        {
            Console.WriteLine("SendAddCharacter!!");
            SyncCharacterArgs args = new SyncCharacterArgs();
            args.Message = s;
            OnSyncCharacterMessage(args);
        }
        protected virtual void OnSyncCharacterMessage(SyncCharacterArgs e)
        {
            Console.WriteLine("OnAddCharacter!!");
            EventHandler<SyncCharacterArgs> handler = SyncCharacterMessage;
            if (handler != null)
            {
                handler(this, e);
            }
        }


        /// <summary>
        /// Start Trun
        /// </summary>
        /// <param name="s"></param>
        private void SendStartTurnMessage(String s)
        {
            Console.WriteLine("Send Start Turn!!");
            StartTurnEventArgs args = new StartTurnEventArgs();
            args.character = s;
            OnStartTurnMessage(args);
        }
        protected virtual void OnStartTurnMessage(StartTurnEventArgs e)
        {
            Console.WriteLine("On Start Turn!!");
            EventHandler<StartTurnEventArgs> handler = StartTurn;
            if (handler != null)
            {
                handler(this, e);
            }
        }


        /// <summary>
        /// Start Trun
        /// </summary>
        /// <param name="s"></param>
        private void SendSuggestionMadeMessage(String message, String suggester)
        {
            Console.WriteLine("Send Suggestion made!!");
            SuggestionMadeEventArgs args = new SuggestionMadeEventArgs();
            args.message = message;
            args.suggester = suggester;
            OnSuggestionMadeMessage(args);
        }
        protected virtual void OnSuggestionMadeMessage(SuggestionMadeEventArgs e)
        {
            Console.WriteLine("On Suggestion made!!");
            EventHandler<SuggestionMadeEventArgs> handler = SuggestionMade;
            if (handler != null)
            {
                handler(this, e);
            }
        }


        /// <summary>
        /// Start Trun
        /// </summary>
        /// <param name="s"></param>
        private void SendDisproveMadeMessage(String message, String suggester)
        {
            Console.WriteLine("Send Suggestion made!!");
            SuggestionMadeEventArgs args = new SuggestionMadeEventArgs();
            args.message = message;
            args.suggester = suggester;
            OnDisproveMadeMessage(args);
        }
        protected virtual void OnDisproveMadeMessage(SuggestionMadeEventArgs e)
        {
            Console.WriteLine("On Suggestion made!!");
            EventHandler<SuggestionMadeEventArgs> handler = DisproveMade;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        
        /// <summary>
        /// Start Trun
        /// </summary>
        /// <param name="s"></param>
        private void SendAccusationResponseMadeMessage(String message, String suggester)
        {
            Console.WriteLine("Send Accusation made!!");
            SuggestionMadeEventArgs args = new SuggestionMadeEventArgs();
            args.message = message;
            args.suggester = suggester;
            OnAccusationResponseMadeMessage(args);
        }
        protected virtual void OnAccusationResponseMadeMessage(SuggestionMadeEventArgs e)
        {
            Console.WriteLine("On Accusation made!!");
            EventHandler<SuggestionMadeEventArgs> handler = AccusationResponse;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        /// <summary>
        /// Start Trun
        /// </summary>
        /// <param name="s"></param>
        private void SendPlayerLostMessage(String suggester)
        {
            Console.WriteLine("Send palyerlost made!!");
            SuggestionMadeEventArgs args = new SuggestionMadeEventArgs();
            args.suggester = suggester;
            OnPlayerLostMadeMessage(args);
        }
        protected virtual void OnPlayerLostMadeMessage(SuggestionMadeEventArgs e)
        {
            Console.WriteLine("On plsyerloer made!!");
            EventHandler<SuggestionMadeEventArgs> handler = PlayerLost;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        
    }



    public class StartTurnEventArgs : EventArgs
    {
        public String character { get; set; }
    }

    public class SyncCharacterArgs : EventArgs
    {
        public String Message { get; set; }
    }
    public class AddCardEventArgs : EventArgs
    {
        public MessageType messageType { get; set; }
        public String cardName { get; set; }
    }

    public class DebugMessageEventArgs : EventArgs
    {
        public MessageType messageType { get; set; }
        public String message { get; set; }
    }

    public class CharacterSelectEventArgs : EventArgs
    {
        public String names { get; set; }
    }

    public class SuggestionMadeEventArgs : EventArgs
    {
        public String message { get; set; }
        public String suggester { get; set; }
    }
}
